--[[ 
	oUF_P3lim layout for oUF

	### READ THIS ###
	If you intend to change anything in here its up to you and you cannot report bugs on a modified layout.
	When you are changing anything here you would like to refer to these 3 links before you ask anyone about anything:

	http://www.lua.org/pil/
	http://www.wowwiki.com/Widget_API
	http://www.wowwiki.com/World_of_Warcraft_API
--]]

-- This one toggles which raid frames are shown.
-- Use 'true' to make them look like party, 'false' to make them look like grid.
local oldParty = true
-- Also, party is controlled in raid by the default option found in Interface Options: "Hide Party Interface in Raid".

local select = select
local UnitName = UnitName
local UnitLevel = UnitLevel
local UnitClass = UnitClass
local UnitIsDead = UnitIsDead
local UnitIsGhost = UnitIsGhost
local UnitIsPlayer = UnitIsPlayer
local UnitIsTapped = UnitIsTapped
local UnitReaction = UnitReaction
local UnitPowerType = UnitPowerType
local UnitIsConnected = UnitIsConnected
local UnitReactionColor = UnitReactionColor
local UnitIsTappedByPlayer = UnitIsTappedByPlayer
local UnitClassification = UnitClassification
local RAID_CLASS_COLORS = RAID_CLASS_COLORS

local LibDruidMana, LibMobHealth
local statusbar, druidMana = "Interface\\AddOns\\oUF_P3lim\\media\\statusbar"
local backdrop = {
	bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
	insets = {left = -1.5, right = -1.5, top = -1.5, bottom = -1.5},
}

if LibStub then LibMobHealth = LibStub("LibMobHealth-4.0", true) end
if LibStub then LibDruidMana = LibStub("LibDruidMana-1.0", true) end

local menu = function(self)
	local unit = self.unit:sub(1, -2)
	local cunit = self.unit:gsub("(.)", string.upper, 1)

	if(unit == "party" or unit == "partypet") then
		ToggleDropDownMenu(1, nil, _G["PartyMemberFrame"..self.id.."DropDown"], "cursor", 0, 0)
	elseif(_G[cunit.."FrameDropDown"]) then
		ToggleDropDownMenu(1, nil, _G[cunit.."FrameDropDown"], "cursor", 0, 0)
	end
end

local updateHealth = function(self, event, bar, unit, min, max)
	local deficit, cur, maxhp = min-max
	if LibMobHealth then cur, maxhp = LibMobHealth:GetUnitHealth(unit) end

	if UnitIsDead(unit) then
		bar:SetValue(0)
		bar.value:SetText"Dead"
	elseif UnitIsGhost(unit) then
		bar:SetValue(0)
		bar.value:SetText"Ghost"
	elseif(not UnitIsConnected(unit)) then
		bar.value:SetText"Offline"
	elseif unit == "pet" then
		bar.value:SetFormattedText("%d |cff0090ff/|r %d", min, max)
	elseif unit == "player" then
		if min ~= max then
			local percent = floor(min/max*100)
			bar.value:SetFormattedText("|cffff8080%d|r / %d|cff0090ff%%|r", deficit, percent)
		else
			bar.value:SetText(max)
		end
	elseif(self:GetParent():GetName()=="oUF_Party" or self:GetParent():GetName():sub(1,8)=="oUF_Raid") then
		if min ~= max then
			bar.value:SetText(deficit)
		else
			bar.value:SetText()
		end
	else
		if max == 100 then
			if unit == "target" and LibMobHealth and not UnitIsPlayer("target") then
				local percent = floor(cur/maxhp*100)
				bar.value:SetFormattedText("%d (%d|cff0090ff%%|r)", cur, percent)
			else
				bar.value:SetFormattedText("%d|cff0090ff%%", min)
			end
		else
			bar.value:SetFormattedText("%d |cff0090ff/|r %d", min, max)
		end
	end

	if(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) or not UnitIsConnected(unit)) then
		bar:SetStatusBarColor(.6,.6,.6)
	elseif(self:GetParent():GetName():sub(1,8)=="oUF_Raid") then
		local color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
		if color then bar:SetStatusBarColor(color.r, color.g, color.b) end
	else
		bar:SetStatusBarColor(.25,.25,.35)
	end
end

local updatePower = function(self, event, bar, unit, min, max)
	local deficit = min - max
	if UnitIsPlayer(unit) then
		if min == 0 then
			bar.value:SetText()
		elseif(not UnitIsConnected(unit)) then
			bar.value:SetText()
		elseif unit == "player" then
			if min ~= max then
	            bar.value:SetText(max-(max-min))
	        else
				bar.value:SetText(max)
			end
		else
			if min ~= max then
				bar.value:SetFormattedText("%d|cff0090ff - ", max-(max-min))
			else
				bar.value:SetFormattedText("%d|cff0090ff - ", max)
			end
		end
	else
		bar.value:SetText()
	end

	local color
	if unit == "pet" then
		color = oUF.colors.happiness[GetPetHappiness()] or oUF.colors.power[UnitPowerType(unit)]
	elseif UnitIsPlayer(unit) then
		color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
	else
		color = UnitReactionColor[UnitReaction(unit, "player")]
	end
	if color then bar:SetStatusBarColor(color.r, color.g, color.b) end
end

local typFormats = {
	["worldboss"] = "%s |cff0090ffBoss|r",
	["rareelite"] = "%s |cff0090ff%s+ Rare|r",
	["elite"] = "%s |cff0090ff%s+|r",
	["rare"] = "%s |cff0090ff%s Rare|r",
	["normal"] = "%s |cff0090ff%s|r",
}

local updateName = function(self, event, unit)
	if(self.unit ~= unit) then return end

	local name = UnitName(unit)
	local lvl = UnitLevel(unit)
	local typ = UnitClassification(unit)

	if lvl < 0 then lvl = "??" end -- slight hack
	
	if(unit == "target") then
		self.Name:SetFormattedText(typFormats[typ], name, lvl)
	else
		self.Name:SetText(name)
	end
end

local CreateAuraIcon = function(self, button, icons, index, isDebuff)
	local tex = button:CreateTexture(nil, "OVERLAY")
	tex:SetTexture("Interface\\AddOns\\oUF_P3lim\\media\\border")
	tex:SetAllPoints(button)
	tex:SetVertexColor(.25,.25,.35)

	button.icon:SetTexCoord(.07, .93, .07, .93)
	if isDebuff then
		button.overlay:Hide()
		button.overlay = tex
	end
end

if LibDruidMana then
	LibDruidMana:AddListener(function(currMana, maxMana)
		if currMana ~= maxMana then
			local perc = floor(currMana/maxMana*100)
			druidMana:SetFormattedText("%d|cff0090ff%%|r", perc)
		else
			druidMana:SetText()
		end
	end)
end

local func = function(settings, self, unit)
	self.menu = menu
	self:SetScript("OnEnter", UnitFrame_OnEnter)
	self:SetScript("OnLeave", UnitFrame_OnLeave)
	self:RegisterForClicks"anyup"
	self:SetAttribute("*type2", "menu")

	if unit == "targettarget" or unit == "focus" then
		self:SetWidth(150)
		self:SetHeight(21)
	elseif unit == "player" or unit == "target" then
		self:SetWidth(180)
		self:SetHeight(21)
	elseif unit == "pet" then
		self:SetWidth(126)
		self:SetHeight(30)
	end

	self:SetBackdrop(backdrop)
	self:SetBackdropColor(0,0,0,1)

	local hp = CreateFrame"StatusBar"
	hp:SetHeight(unit and 17.5 or 17.5)
	hp:SetStatusBarTexture(statusbar)
	hp:SetParent(self)
	hp:SetPoint"TOP"
	hp:SetPoint"LEFT"
	hp:SetPoint"RIGHT"

	local hpbg = hp:CreateTexture(nil, "BORDER")
	hpbg:SetAllPoints(hp)
	hpbg:SetTexture(.25,.25,.25)

	local hpp = hp:CreateFontString(nil, "OVERLAY")
	hpp:SetPoint("RIGHT", -2, -1)
	hpp:SetFontObject(GameFontNormalSmall)
	hpp:SetTextColor(1,1,1)

	hp.bg = hpbg
	hp.value = hpp
	self.Health = hp
	self.OverrideUpdateHealth = updateHealth

	local pp = CreateFrame("StatusBar")
	pp:SetHeight(unit and 2 or 2)
	pp:SetStatusBarTexture(statusbar)
	pp:SetParent(self)
	pp:SetPoint"LEFT"
	pp:SetPoint"RIGHT"
	pp:SetPoint("TOP", hp, "BOTTOM", 0, -1.35)

	local ppbg = pp:CreateTexture(nil, "BORDER")
	ppbg:SetAllPoints(pp)
	ppbg:SetTexture(.25,.25,.25)

	local ppp = pp:CreateFontString(nil, "OVERLAY")
	ppp:SetFontObject(GameFontNormalSmall)
	ppp:SetTextColor(1,1,1)
	ppp:SetPoint("RIGHT", hpp, "LEFT")

	if(not(unit == "player" or unit == "target")) then ppp:Hide() end

	pp.bg = ppbg
	pp.value = ppp
	self.Power = pp
	self.OverrideUpdatePower = updatePower

	local leader = hp:CreateTexture(nil, "OVERLAY")
	leader:SetHeight(16)
	leader:SetWidth(16)
	leader:SetPoint("TOPLEFT", self, 0, 8)
	leader:SetTexture"Interface\\GroupFrame\\UI-Group-LeaderIcon"
	self.Leader = leader

	local icon = hp:CreateTexture(nil, "OVERLAY")
	icon:SetHeight(16)
	icon:SetWidth(16)
	icon:SetPoint("TOP", self, 0, 8)
	icon:SetTexture"Interface\\TargetingFrame\\UI-RaidTargetingIcons"
	self.RaidIcon = icon

	if(not(unit == "player" or unit == "pet")) then
		local name = hp:CreateFontString(nil, "OVERLAY")
		name:SetPoint("LEFT", 2, -1)
		name:SetPoint("RIGHT", ppp, "LEFT")
		name:SetJustifyH"LEFT"
		name:SetFontObject(GameFontNormalSmall)
		name:SetTextColor(1,1,1)
		self.Name = name
		self.UNIT_NAME_UPDATE = updateName
	end

	if unit == "player" then
		if LibDruidMana then
			local druid = hp:CreateFontString(nil, "OVERLAY")
			druid:SetFontObject(GameFontNormalSmall)
			druid:SetTextColor(1,1,1)
			druid:SetPoint("CENTER", pp)
			druidMana = druid
		end
		self.ignoreBanzai = true

		ppp:SetPoint("LEFT", hp, "LEFT", 2, -1)
		ppp:SetJustifyH"LEFT"
	end

	if unit == "pet" or unit == "target" then
		local buffs = CreateFrame("Frame", nil, self)
		buffs.spacing = 1.1
		if unit == "pet" then
			buffs:SetPoint("TOPRIGHT", self, "TOPLEFT", -3, 1)
			buffs["growth-x"] = "LEFT"
			buffs.initialAnchor = "TOPRIGHT"
			buffs.filter = true
		elseif unit == "target" then
			buffs:SetPoint("TOPLEFT", self, "TOPRIGHT", 3, 1)
			buffs.initialAnchor = "TOPLEFT"
		end
		buffs.size = hp:GetHeight() * 1.1
		buffs:SetWidth(buffs.size * 10)
		buffs:SetHeight(buffs.size * 2)
		buffs.num = 20
		buffs["growth-y"] = "DOWN"
		self.Buffs = buffs
	end

	if unit == "pet" or unit == "target" or unit == "targettarget" or unit == "focus" then
		local debuffs = CreateFrame("Frame", nil, self)
		debuffs.spacing = 1.2
		if unit == "pet" or unit == "target" then
			debuffs.size = hp:GetHeight() * .97
			debuffs:SetPoint("TOPLEFT", self, "BOTTOMLEFT", -1.5, -4)
			debuffs.initialAnchor = "TOPLEFT"
			if unit == "pet" then
				debuffs:SetWidth(debuffs.size * 6)
				debuffs:SetHeight(debuffs.size)
				debuffs.num = 6
			elseif unit == "target" then
				debuffs:SetWidth(debuffs.size * 20)
				debuffs:SetHeight(debuffs.size * 2)
				debuffs.num = 20
				debuffs["growth-y"] = "DOWN"
			end
		elseif unit == "targettarget" or unit == "focus" then
			hp:SetHeight(17.5)
			pp:SetHeight(2)
			if unit == "targettarget" then
				debuffs:SetPoint("RIGHT", self, "LEFT", -3, 0)
				debuffs["growth-x"] = "LEFT"
				debuffs.initialAnchor = "TOPRIGHT"
			elseif unit == "focus" then
				debuffs:SetPoint("LEFT", self, "RIGHT", 3, 0)
				debuffs.initialAnchor = "TOPLEFT"
			end
			debuffs.size = self:GetHeight() * 1.1
			debuffs:SetWidth(debuffs.size * 3)
			debuffs:SetHeight(debuffs.size)
			debuffs.num = 3
		end
		self.Debuffs = debuffs
	end
	
	if(not unit) then
		local auras = CreateFrame("Frame", nil, self)
		auras.spacing = 1.1
		auras.size = 21 * 0.7
		auras:SetHeight(auras.size)
		auras:SetWidth(auras.size * 8)
		auras:SetPoint("LEFT", self, "RIGHT", 4, 0)
		auras.initialAnchor = "BOTTOMLEFT"
		auras.numBuffs = 4
		auras.numDebuffs = 4
		self.Auras = auras

		self.outsideRangeAlpha = 1
		self.inRangeAlpha = 1
		self.Range = true
	else
		local cf = hp:CreateFontString(nil, "OVERLAY")
		cf:SetPoint("CENTER", 0, 1)
		cf:SetFont("Interface\\AddOns\\oUF_P3lim\\media\\font.ttf", 18)
		self.CombatFeedbackText = cf
	end
	
	if select(2, UnitClass"player") == "ROGUE" or select(2, UnitClass"player") == "DRUID" then
		if unit == "target" then
			local cpoints = self:CreateFontString(nil, "OVERLAY")
			cpoints:SetPoint("RIGHT", self, "LEFT", -9, 3)
			cpoints:SetFont("Interface\\AddOns\\oUF_P3lim\\media\\font.ttf", 38, "OUTLINE")
			cpoints:SetTextColor(1,1,1)
			cpoints:SetJustifyH"RIGHT" 
			self.CPoints = cpoints
		elseif unit == "player" then
			local spark = pp:CreateTexture(nil, "OVERLAY")
			spark:SetTexture"Interface\\CastingBar\\UI-CastingBar-Spark"
			spark:SetBlendMode"ADD"
			spark:SetHeight(pp:GetHeight() * 2)
			spark:SetWidth(pp:GetHeight() * 2)
			self.Spark = spark
		end
	end

	self.PostCreateAuraIcon = CreateAuraIcon
	self.DebuffHighlightBackdrop = true
	self.DebuffHighlightFilter = true

	return self
end

local raidfunc = function(settings, self, unit)
	self:SetScript("OnEnter", UnitFrame_OnEnter)
	self:SetScript("OnLeave", UnitFrame_OnLeave)

	self:SetBackdrop(backdrop)
	self:SetBackdropColor(0,0,0,1)

	local hp = CreateFrame("StatusBar")
	hp:SetHeight(21)
	hp:SetWidth(50)
	hp:SetStatusBarTexture"Interface\\AddOns\\oUF_P3lim\\media\\statusbar"
	hp:SetParent(self)
	hp:SetPoint"CENTER"

	local hpbg = hp:CreateTexture(nil, "BORDER")
	hpbg:SetAllPoints(hp)
	hpbg:SetTexture(.25,.25,.25)

	local hpp = hp:CreateFontString(nil, "ARTWORK")
	hpp:SetPoint("RIGHT", -2, -1)
	hpp:SetFontObject(GameFontNormalSmall)
	hpp:SetTextColor(1,1,1)

	hp.bg = hpbg
	hp.value = hpp
	self.Health = hp
	self.OverrideUpdateHealth = updateHealth

	local icon = hp:CreateTexture(nil, "OVERLAY")
	icon:SetHeight(16)
	icon:SetWidth(16)
	icon:SetPoint("TOP", self, 0, 8)
	icon:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
	self.RaidIcon = icon

	local leader = hp:CreateTexture(nil, "OVERLAY")
	leader:SetHeight(16)
	leader:SetWidth(16)
	leader:SetPoint("TOPLEFT", self, 0, 8)
	leader:SetTexture"Interface\\GroupFrame\\UI-Group-LeaderIcon"
	self.Leader = leader

	local dbh = hp:CreateTexture(nil, "OVERLAY")
	dbh:SetHeight(10)
	dbh:SetWidth(10)
	dbh:SetPoint("CENTER", hp)
	dbh:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background")
	dbh:SetBlendMode"ADD"
	dbh:SetVertexColor(0,0,0,0)
	self.DebuffHighlight = dbh
	self.DebuffHighlightAlpha = 1
	self.DebuffHighlightFilter = true

	self.Range = true
	self.inRangeAlpha = 1
	self.outsideRangeAlpha = .3

	return self
end

oUF:RegisterStyle("P3lim", setmetatable({}, {__call = func}))
oUF:RegisterStyle("P3lim_Party", setmetatable({
	["initial-width"] = 110,
	["initial-height"] = 21,
}, {__call = func}))
oUF:RegisterStyle("P3lim_Raid", setmetatable({
	["initial-width"] = 50,
	["initial-height"] = 21,
}, {__call = raidfunc}))

oUF:SetActiveStyle("P3lim")

local player = oUF:Spawn"player"
player:SetPoint("CENTER", -160, -140)
local target = oUF:Spawn"target"
target:SetPoint("CENTER", 160, -140)
local pet = oUF:Spawn"pet"
pet:SetPoint("RIGHT", player, "LEFT", -25, 0)
local tot = oUF:Spawn"targettarget"
tot:SetPoint("BOTTOMRIGHT", target, "TOPRIGHT", 0, 7)
local focus = oUF:Spawn"focus"
focus:SetPoint("BOTTOMLEFT", player, "TOPLEFT", 0, 9)

oUF:SetActiveStyle("P3lim_Party")

local party	= oUF:Spawn("header", "oUF_Party")
party:SetPoint("BOTTOMLEFT", 15, 140)
party:SetAttribute("yOffset", -5)

if oldParty then
	local toggleParty = CreateFrame("Frame")
	toggleParty:SetScript("OnEvent", function(self)
		if(InCombatLockdown()) then self:RegisterEvent"PLAYER_REGEN_ENABLED"
		else self:UnregisterEvent"PLAYER_REGEN_ENABLED"
			if HIDE_PARTY_INTERFACE == "1" and GetNumRaidMembers() > 0 then
				party:SetManyAttributes("showParty", false, "showRaid", true)
				party:Show()
			else
				party:SetManyAttributes("showParty", true, "showRaid", false)
				party:Show()
			end
		end
	end)
	toggleParty:RegisterEvent"PARTY_MEMBERS_CHANGED"
	toggleParty:RegisterEvent"PARTY_LEADER_CHANGED"
	toggleParty:RegisterEvent"RAID_ROSTER_UPDATE"
	toggleParty:RegisterEvent"PLAYER_LOGIN"
else
	oUF:SetActiveStyle("P3lim_Raid")

	local last = {}
	for i = 1, 5 do
		local raid = oUF:Spawn("header", "oUF_Raid"..i)
		raid:SetManyAttributes("groupFilter", tostring(i), "showRaid", true, "yOffSet", -5)
		table.insert(last, raid)
		if i == 1 then
			raid:SetPoint("BOTTOMLEFT", UIParent, "BOTTOM", -140, 90) -- 2nd number = height
		else
			raid:SetPoint("TOPLEFT", last[i-1], "TOPRIGHT", 8, 0)
		end
		raid:Show()
	end

	local toggleParty = CreateFrame("Frame")
	toggleParty:SetScript("OnEvent", function(self)
		if(InCombatLockdown()) then self:RegisterEvent"PLAYER_REGEN_ENABLED"
		else self:UnregisterEvent"PLAYER_REGEN_ENABLED"
			if HIDE_PARTY_INTERFACE == "1" and GetNumRaidMembers() > 0 then
				party:SetAttribute("showParty", false)
			else
				party:SetAttribute("showParty", true)
				party:Show()
			end
		end
	end)
	toggleParty:RegisterEvent"PARTY_MEMBERS_CHANGED"
	toggleParty:RegisterEvent"PARTY_LEADER_CHANGED"
	toggleParty:RegisterEvent"RAID_ROSTER_UPDATE"
	toggleParty:RegisterEvent"PLAYER_LOGIN"
end
